C++开发环境构建
C++的开发环境,目前常用的IDE是vscode。 macOS安装 开发工具(例如xcode、commondlinetools) 之后,其包含了c++的标准库。
通过环境变量等方法正确的引入标准库以及三方库 即可实现 基于vscode开发 c++的项目。
然而,环境搭建的过程中,重要的是:
- 对于编译器、构建工具、库及其管理 的理解、对C++版本的理解。
- 如何使用 vscode、clang++、make、cmake 开发和构建 c++的项目;如何debug调试;以及理解这些工具和过程的原理。
- 可能会遇到哪些常见的问题? 怎么解决、以及怎么持续深入学习c++的项目。
1.编译器
常见的编译器有:GCC、Clang、Microsoft Visual C++等等。
clang更加现代化、模块化,编译速度更快,适合大型项目
许多编译器即支持c也支持c++,但对于c++的一些新特性和复杂的语法结构,编译器的优化和处理可能有所不同。
1.1 编译和运行
最简单的C程序1
2
3
4
5
6
int main()
{
printf("This is a C program.\n");
return 0;
}
编译与运行1
2
3
4
5gcc helloworld.c -o helloworld
# 或者 clang example.c -o example
./helloworld
# 输出结果
This is a C program.
2. c++版本/clang版本
不同来源版本的clang可能存在差异
mac系统自带的Clang编译器不支持OpenMP,需要手动安装Clang(基于llvm),即 brew install llvm.
然后配置环境变量,后续所有开发场景都可以使用此版本的clang和基于llvm的工具。
clang++版本
这些编译工具(clang/g++) 路径在xcode或者commondlinetools 路径下.
1.怎么理解c++的版本?
2.clang的版本和c++版本的关系?
3.clang版本的区别?和make有兼容性问题吗?
4.怎么查看c++的库路径和版本信息?
mac系统库路径一般在:/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib
1 | libc++.1.tbd |
.tbd 是苹果操作系统的文件格式,用于描述动态库的符号信息。以上3个是C++标准库的实现。
linux中呢?
3.库和库管理
c++相关的库 一般在开发工具的环境路径/目录(/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib)、
以及 系统的基础lib路径(/usr/lib、/usr/local/lib/)下。 例如mac中,在xcode、Command Line Tools 工具的路径下。
开发环境、运行时环境项目 会从这些路径下找 需要的库内容。 「c++主要涉及 头文件(include)、库文件(lib)路径」
3.1 库
c++的库.
3.1.1 C++标准库
提供了一些列重要的模块。
(容器、算法、迭代器、字符串、输入输出、智能指针、线程、日期和时间、类型特性、元编程、异常处理等)
3.1.2 STL和Boost
STL 和 Boost 是 C++ 开发中两个重要的库。
STL(标准模板库)是 C++ 标准库的一部分
Boost 是一个大型的开源 C++ 库集合,它提供了许多扩展功能和库,这些库在功能和性能上都经过了严格的测试和验证。Boost 的设计目的是为 C++ 开发者提供可重用的组件,许多 Boost 库的设计理念和接口最终被采纳到 C++ 标准库中。
STL 是 C++ 开发的基础库,而 Boost 则是 C++ 开发的高级库,提供了更多扩展和增强功能。两者在 C++ 编程中各有其重要作用,Boost 库中的许多功能也为 C++ 标准库的演进做出了贡献。
3.2 库管理
介绍下 通过环境变量 正确、方便的 引入开发环境/项目。
另外介绍下 常见的安装的软件的 开发相关的库。
项目是如果找到 这些库的呢?
以c++库和头文件为例:
- 当前目录、当前项目
- 编译时指定的头文件目录(有 -I -L 参数指定)
- 系统环境变量 CPLUS_INCLUDE_PATH 或 C_INCLUDE_PATH 指定的目录
- gcc默认目录: /usr/include;/usr/local/include;等等.(各系统平台可能会有不同)
3.2.1 环境变量
和java同理,要用这些 不同路径下的 库和头文件,可能会涉及 环境变量的配置。 或者ide环境的配置。
主要目的是通过环境变量 正确、方便的 将需要的库引入开发环境/项目。
(有些ide中直接配置即可,不用配置环境变量;但通过环境变量配置可能后续使用起来更方便些)
常见的库路径如下:
来源 | 说明 | 路径 |
---|---|---|
CommandLineTools | CommandLineTools | /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include |
XCode | XCode | /Applications/Xcode.app/Contents/Developer/Platforms/ MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib |
系统库 | 通常是系统自带的库文件(属于系统核心部分) | /usr/lib/ |
系统(手动安装) | 类Unix系统(如macOS/Linux)中常用的目录,存放本地安装的库文件(手动或第三方软件安装) | /usr/local/lib/ |
本地头文件 | 类Unix系统(如macOS/Linux)中常用的目录,存放本地安装的库文件(手动或第三方软件安装) | /usr/local/include/ |
当手动安装或者下载的第三方的软件的路在别的指定路径下,需要在某个项目中使用时。 相关的库和头文件 路径可以通过 环境变量的配置引入项目。 例如:
1 | export CPATH=$CPATH:/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib |
3.2.2 CommandLineTools和XCode
这两个都是mac上的开发工具。 CommandLineTools 是轻量级的,主要提供了命令行开发工具; XCode是功能强大的集成开发环境(IDE).
如果是iOS、macOS、watchOS和tvOS的开发,可以安装XCode; 其它情况,建议安装CommandLineTools即可(仅几百M)
类型 | CommandLineTools | XCode |
---|---|---|
安装包大小 | 几百M | 几个GB,甚至10多GB |
用途 | 主要提供命令行工具,如编译器(Clang、GCC等)、链接器、调试器(LLDB)和其他基本的开发工具 | 功能强大的集成开发环境(IDE),代码编辑、调试、界面设计、版本控制等;模拟器、性能分析、测试等高级功能 |
使用场景 | 常用于 脚本编写、小型项目开发、自动化构建等 | 适合专业的IOS和macOS应用程序开发,以及需要图形界面设计和高级开发功能的项目 |
更新方式 | 通过命令行工具(如xcode-select —install) | 通过Mac App Store进行更新,需要较长时间 |
一些c++的项目,需要的 三方库和头文件,可以通过引入 CommandLineTools 下的。
3.2.3 llvm和clang
1.什么是LLVM?
LLVM(Low Level Virtual Machine) 是一个开源的 编译器基础设施项目。
2.包含的工具集?
- 包括Clang编译器,它是一个基于LLVM的C、C++和Objective-C 编译器。
- LLDB调试器,用于调试程序。
- 其他工具如lli(LLVM解释器)、llvm-link(链接器)等
3.有什么特点和优势?
- 可扩展性、性能优化、跨平台、开源和活跃的社区。
4.能做什么?
- 编译器开发
- 代码优化
- 程序分析和调试
- 跨平台开发
- 工具和库(Clang、LLDB、Polly)
安装和查看1
2
3
4
5
6
7
8
9
10
11# mac默认的一般是 基于xcode中的。 建议自己安装
brew install llvm
# 查看
brew info llvm
# 配置环境变量
export PATH="/usr/local/opt/llvm/bin:$PATH"
## 这样 clang也是基于llvm的。 而不是基于xcode的clang 15.0.0版本
## 实质的 安装路径在:/usr/local/Cellar/llvm/ /usr/local/opt/llvm/ 是链接过去的
## 不同版本的macOS系统,homebrew 安装这种三方工具的 路径不太一样(新版系统 在/opt/homebrew/...)
3.2.4 GCC和GDB
重点:谈到 llvm和clang, 同样的介绍下 GCC和GDB。
- clang是LLVM项目的一部分, 是一个开源的编译器前端。
- 而gcc 是GUN Compiler Collection的缩写,是一个成熟的开源编译器集合
- 使用 Clang 还是 GCC?如果 Clang 能够完全满足你的编译需求, 并且不依赖GCC特有的功能,那么可以仅使用clang。
如果老项目基于GCC,可能需要同时使用gcc和clang。
GDB 类似 lldb 主要用于调试(生成调试信息)。
两者的比较:
LLVM 和 Clang 在设计上较为现代,提供了优秀的错误和警告信息、更快的编译速度、更好的 C++ 标准支持和先进的静态分析工具。
GCC 依然是一个成熟、稳定且功能强大的编译器,具有广泛的语言和平台支持,适合很多传统和生产环境。
4.构建
构建工具 类似java的 maven,用于较大型项目的构建。常见的构建工具包括:make、cmake、bazel。
- make是传统的构建工具,简单高效,适合小到中型项目、在Unix和类Unix系统上使用。
- cmake是跨平台(win/linux/macOS/android等)的构建工具,广泛用于C和C++项目。 通过「CMakeLists.txt」描述项目构建过程。
4.1 make
make是个构建工具,类似于maven。
Makefile定义了项目的依赖关系和构建规则。
1.发展背景和现状
make起源于AT&T贝尔实验室,当前由FSF维护, GUN项目提供make的GUN版本。(目前大多数开发环境和操作系统中使用的make实际上是指GUN make,简称make)
2.make的基本概念
Makefile、目标、依赖、规则。
4.1.1 Makefile
Makefile的基本结构
1 | # 变量定义 「定义了 (CC) 和编译选项 (CFLAGS)」 |
xgboost的Makefile解读
1 | # 变量定义 「定义了 (CC) 和编译选项 (CFLAGS)」 |
构建过程中,是怎么找到依赖的。 比如 每个源文件是单独构建的,构建的时候,如果依赖其它的 构建,这个关系怎么找到的?
也就是说 怎么知道那个需要先构建?
4.2 cmake
CMake是一个 构建系统生成器。 主要作用是 生成特定与平台和构建工具的构建配置文件。
实际的构建过程则依赖生成的这些构建配置文件所对应的构建工具。
4.2.1 什么是cmake
cmake相比较make,有以下优点:
- 跨平台支持:支持多种操作系统,如Linux、macOS、Windows等。能够生成适用于不同平台的构建系统配置文件。
- 构建配置:通过一个或多个CMakeLists.txt文件来描述项目的配置。
- 自动化和简化构建:生成适用于不同构建工具的配置文件, 使得用户可以使用选择喜欢的构建工具(make/MSBuild等)
如果系统中有多个C编译器,可以明确指定要使用的编译器
4.2.2 cmake使用方法
CMakeLists.txt
1. 安装cmake1
2
3
4
5
6
7# macOS
brew install cmake
# linux
sudo apt-get install cmake # 对于 Debian/Ubuntu 系统
sudo yum install cmake # 对于 Red Hat/CentOS 系统
# Window
choco install cmake
2. 创建CMakeLists.txt
CMakeLists.txt 文件是 CMake 的核心配置文件,用于描述构建项目的规则。一个基本的 CMakeLists.txt 文件可能如下所示:
1 | cmake_minimum_required(VERSION 3.10) # 设置 CMake 的最低版本要求 |
3. 创建构建目录1
2mkdir build
cd build
4. 生成构建系统配置文件1
2# 在构建目录中运行 CMake,指定源代码目录(通常是 .. 表示上级目录):
cmake ..
5. 执行构建
使用make等构建工具执行
4.2.3 高级用法
1.定义库1
2add_library(MyLibrary STATIC lib.cpp)
target_link_libraries(MyExecutable PRIVATE MyLibrary)
2.查找和使用外部库1
2
3find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(MyExecutable ${OpenCV_LIBS})
1 | # 设置编译选项: |
4.2.1 版本查看
1 | clang --version |
5.常见库及问题
5.1 xgboost项目构建和调试
xgboost项目构建和调试过程中遇到的问题?
主要就是 mac系统自带的Clang编译器不支持OpenMP,需要手动安装Clang(基于llvm),即 brew install llvm.
(1.)unsupported option ‘-fopenmp’
1.命令1
2clang++ -DDMLC_LOG_CUSTOMIZE=1 -std=c++11 -Wall -Wno-unknown-pragmas -Iinclude -Idmlc-core/include -Irabit/include
-I/include -O3 -funroll-loops -msse2 -fPIC -fopenmp -MM -MT build/learner.o src/learner.cc >build/learner.d
2.现象
clang: error: unsupported option ‘-fopenmp’
make: * [build/learner.o] Error 1
3.问题分析
OpenMP 是一个用于多处理器编程的应用程序接口(API),专门设计用于在共享内存系统上并行化计算密集型任务。
是一种编写并行程序的标准化工具,可以显著简化多线程编程的复杂性。
OpenMP的执行模式采用fork-join模式
出现以上问题,可能的原因有:
- Clang版本不支持OpenMP
- 未安装OpenMP运行时库
- Clang配置问题:你的 Clang 安装可能没有启用 OpenMP 支持。需要确保使用的 Clang 编译器版本正确地配置了 OpenMP。
(重点):1. 开头使用 c++ 进行编译. 2. 改为clang++后还是提示。 因此可能是clang编译器的原因
1 | #macOS 自带的 Clang 编译器可能不支持 OpenMP,因此你可以通过 Homebrew 安装一个支持 OpenMP 的 Clang 版本 |
4.解决办法
1 | # 1. 修改makefile的 变量配置,使其使用clang++ |
mac自带的clang(xcode/commondlinetools) 编译器和基于llvm的编译器存在差异。
mac已经有llvm ,有必要再 brew install llvm 吗?需要通过llvm安装新的clang,并且方便管理维护
6. C++环境验证
6.1 当前环境下使用的 c++的标准库路径?
怎么看当前环境下使用的 c++的标准库路径呢。
1 | # GCC |